package com.geostar.constructionland.attachment.service.planningReview;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.geostar.constructionland.attachment.entity.attachment.AttachmentDirectoryInstEntity;
import com.geostar.constructionland.attachment.entity.attachment.AttachmentEntity;
import com.geostar.constructionland.attachment.entity.attachment.AttachmentVersionEntity;
import com.geostar.constructionland.attachment.entity.attachment.CorrectionAttachmentEntity;
import com.geostar.constructionland.attachment.mapper.attachment.AttachmentDirectoryInstMapper;
import com.geostar.constructionland.attachment.mapper.attachment.AttachmentMapper;
import com.geostar.constructionland.attachment.mapper.attachment.AttachmentVersionMapper;
import com.geostar.constructionland.attachment.mapper.attachment.CorrectionAttachmentMapper;
import com.geostar.constructionland.attachment.mapper.planningReview.PlanningReviewMapper;
import com.geostar.constructionland.attachment.util.MongoDBUtil;
import com.geostar.constructionland.common.entity.response.ServerResponse;
import com.geostar.constructionland.common.util.MultithreadUtil;
import com.geostar.constructionland.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 规划审核
 */
@Slf4j
@Service
public class PlanningReviewService {

    // 代理静态变量，避免反射调用，空指针异常
    public static PlanningReviewService proxy;

    @PostConstruct
    public void init() {
        proxy = this;
    }

    @Autowired
    private MongoDBUtil mongoDBUtil;
    @Autowired
    ObjectMapper objectMapper;
    @Resource
    PlanningReviewMapper planningReviewMapper;
    @Resource
    AttachmentDirectoryInstMapper attachmentDirectoryInstMapper;
    @Resource
    AttachmentMapper attachmentMapper;
    @Resource
    CorrectionAttachmentMapper correctionAttachmentMapper;
    @Resource
    AttachmentVersionMapper attachmentVersionMapper;

    @Value("${automatic.uploadFileUrl}")
    String uploadFileUrl;
    /** 提取附件目录名称（进件） */
    @Value("${automatic.planningReviewExtractAttachmentDirName}")
    String planningReviewExtractAttachmentDirName;
    /** 补正附件目录名称（补正材料） */
    @Value("${automatic.planningReviewCorrectionAttachmentDirName}")
    String planningReviewCorrectionAttachmentDirName;

    /** 材料来源 */
    private final String materialSource = "规划审核";
    // 每个线程处理的数据量
    private static int count = 15;
    // 定义线程池数量
    private static ExecutorService execPool = Executors.newFixedThreadPool(16);

    /**
     * 上传zip压缩包
     * @param ywid
     * @param ywxl
     * @param userId
     * @param userName
     * @param path
     * @param version 附件版本号：1-提取附件，大于1-提取补正附件
     * @return
     * @throws IOException
     */
    @Transactional(propagation = Propagation.NESTED, isolation = Isolation.DEFAULT, readOnly = false, rollbackFor = RuntimeException.class)
    public ServerResponse uploadZipFile(String ywid, String ywxl, String userId, String userName, String path, Integer version) throws Exception {
        ServerResponse serverResponse = ServerResponse.createBySuccessMessage("操作成功！");
        File file = new File(path);    // 创建文件对象，url是目标目录
        if (file.exists()) {   // 目录是否存在
            String firstFjmlid = null;
            String fileName = file.getName();
            // 附件扩展名
            String attachmentExtension = ".zip";
            // 当前时间
            Timestamp currentTimestamp = new Timestamp(new Date().getTime());
            AttachmentDirectoryInstEntity attachmentDirectoryInstEntity = new AttachmentDirectoryInstEntity();
            // 查询是否存在附件目录
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("ywid", ywid);
            String attachmentDirName = "";
            if(version == 1) {
                attachmentDirName = planningReviewExtractAttachmentDirName;
            } else {
                attachmentDirName = planningReviewCorrectionAttachmentDirName +"【V"+ (version - 1) +"】";
            }
            param.put("fileName", attachmentDirName);
            List<Map<String, Object>> result = (List<Map<String, Object>>) planningReviewMapper.queryAttachmentDirectoryInstByName(param);
            if(! CollectionUtils.isEmpty(result)) {
                firstFjmlid = (String) result.get(0).get("FJMLID");
            }
            if(StringUtils.isNotBlank(firstFjmlid)) {
                if(version == 1) {
                    // 删除附件目录：“进件”下的附件
                    planningReviewMapper.deleteExtractAttachment(param);
                    // 删除附件目录：“进件”下的附件目录
                    planningReviewMapper.deleteExtractAttachmentDir(param);
                } else {
                    param.put("version", version);
                    // 删除补正材料附件
                    planningReviewMapper.deleteCorrectionAttachment(param);
                    // 删除补正材料附件目录
                    planningReviewMapper.deleteCorrectionAttachmentDir(param);
                    // 删除补正材料记录
                    planningReviewMapper.deleteCorrectionAttachmentRecord(param);
                    // 删除附件版本记录
//                    planningReviewMapper.deleteAttachmentVersion(param);
                }
            } else {
                firstFjmlid = StringUtil.getUUID();
                // 新增总的附件目录
                attachmentDirectoryInstEntity.setId(StringUtil.getUUID());
                attachmentDirectoryInstEntity.setParentAttachmentDirId("-1");
                attachmentDirectoryInstEntity.setAttachmentDirId(firstFjmlid);
                attachmentDirectoryInstEntity.setAttachmentDirName(attachmentDirName);
                attachmentDirectoryInstEntity.setBusinessId(ywid);
                attachmentDirectoryInstEntity.setSortNo(version);
                attachmentDirectoryInstEntity.setBusinessCode(ywxl);
                attachmentDirectoryInstEntity.setIsRequired(0);
                attachmentDirectoryInstEntity.setMaterialSource(materialSource);
                attachmentDirectoryInstEntity.setIsRequiredOriginal("0");
                attachmentDirectoryInstEntity.setFilterTags(ywxl);
                attachmentDirectoryInstEntity.setCreateUserId(userId);
                attachmentDirectoryInstEntity.setCreateUserName(userName);
                attachmentDirectoryInstEntity.setCreateTime(currentTimestamp);
                attachmentDirectoryInstMapper.insert(attachmentDirectoryInstEntity);
            }
            // 新增压缩包名称命名的附件目录
            String zipFjmlid = StringUtil.getUUID();
            String attachmentDirectoryInstId = StringUtil.getUUID();
            attachmentDirectoryInstEntity = new AttachmentDirectoryInstEntity();
            attachmentDirectoryInstEntity.setId(attachmentDirectoryInstId);
            attachmentDirectoryInstEntity.setParentAttachmentDirId(firstFjmlid);
            attachmentDirectoryInstEntity.setAttachmentDirId(zipFjmlid);
            attachmentDirectoryInstEntity.setAttachmentDirName(fileName);
            attachmentDirectoryInstEntity.setBusinessId(ywid);
            attachmentDirectoryInstEntity.setSortNo(1);
            attachmentDirectoryInstEntity.setBusinessCode(ywxl);
            attachmentDirectoryInstEntity.setIsRequired(0);
            attachmentDirectoryInstEntity.setMaterialSource(materialSource);
            attachmentDirectoryInstEntity.setIsRequiredOriginal("0");
            attachmentDirectoryInstEntity.setFilterTags(ywxl);
            attachmentDirectoryInstEntity.setCreateUserId(userId);
            attachmentDirectoryInstEntity.setCreateUserName(userName);
            attachmentDirectoryInstEntity.setCreateTime(currentTimestamp);
            attachmentDirectoryInstMapper.insert(attachmentDirectoryInstEntity);
            if(version > 1) {
                // 新增补正附件记录
                CorrectionAttachmentEntity correctionAttachmentEntity = new CorrectionAttachmentEntity();
                correctionAttachmentEntity.setId(StringUtil.getUUID());
                correctionAttachmentEntity.setBusinessId(ywid);
                correctionAttachmentEntity.setAttachmentId(attachmentDirectoryInstId);
                correctionAttachmentEntity.setType(1);
                correctionAttachmentEntity.setVersion(version);
                correctionAttachmentEntity.setCreateUserId(userId);
                correctionAttachmentEntity.setCreateUserName(userName);
                correctionAttachmentEntity.setCreateTime(currentTimestamp);
                correctionAttachmentMapper.insert(correctionAttachmentEntity);
            }
            // 新增附件
            /** 批量上传文件 */
            MultithreadUtil multithreadUtil = new MultithreadUtil(execPool, count);
            String classPath = "com.geostar.constructionland.attachment.service.planningReview.PlanningReviewService";
            String methodName = "uploadFile";
            @SuppressWarnings("rawtypes")
            Class[] paramClasss = {String.class, String.class, String.class, Integer.class, String.class, String.class,
                        String.class, String.class, String.class, String.class, String.class, Integer.class, Integer.class, Integer.class};
            List<Object[]> params = new ArrayList<Object[]>();
            // 上传压缩包
            Object[] arr = {path + attachmentExtension, fileName + attachmentExtension, firstFjmlid, 1,
                            attachmentExtension, attachmentExtension, userId, userName, null, ywid, ywxl, 0, 0, version};
            params.add(arr);
            saveAttachmentDir(params, ywid, ywxl, userId, userName, path, zipFjmlid, version);
            // 多线程请求坐标转换服务
            multithreadUtil.processingDataBatch(classPath, methodName, paramClasss, params);
        } else {
            throw new Exception("文件解析失败，请重新下载！");
        }
        return serverResponse;
    }

    /**
     * 保存附件目录
     * @param ywid
     * @param ywxl
     * @param userId
     * @param userName
     * @param path
     * @param parentAttachmentDirId
     * @param version
     * @throws IOException
     */
    private void saveAttachmentDir(List<Object[]> params, String ywid, String ywxl, String userId, String userName,
                                   String path, String parentAttachmentDirId, Integer version) throws Exception {
        File file = new File(path);    // 创建文件对象，url是目标目录
        if (file.exists()) {   // 目录是否存在
            File[] files = file.listFiles();    // 读取文件夹下的所有文件
            int dirNum = 0, fileNum = 0;
            for (int i = 0; i < files.length; i++) {
                String fileName = files[i].getName();
                // 当前时间
                Timestamp currentTimestamp = new Timestamp(new Date().getTime());
                if (files[i].isFile()) { // 判断是否是文件
                    fileNum++;
                    // 附件扩展名
                    String attachmentExtension = fileName.substring(fileName.lastIndexOf("."));
//                    System.out.println("第" + fileNum + "个文件的名字是：" + fileName);
                    /** 上传文件 */
                    Object[] arr = {path + File.separator + fileName, fileName, parentAttachmentDirId, fileNum,
                                    attachmentExtension, attachmentExtension, userId, userName, null, ywid, ywxl, 0, 0, version};
                    params.add(arr);
                } else {
                    dirNum++;
//                    System.out.println("第" + dirNum + "个目录的名字是：" + fileName);
                    /** 新增附件目录实例记录 */
                    String nextParentAttachmentDirId = StringUtil.getUUID();
                    String attachmentId = StringUtil.getUUID();
                    AttachmentDirectoryInstEntity attachmentDirectoryInstEntity = new AttachmentDirectoryInstEntity();
                    attachmentDirectoryInstEntity.setId(attachmentId);
                    attachmentDirectoryInstEntity.setParentAttachmentDirId(parentAttachmentDirId);
                    attachmentDirectoryInstEntity.setAttachmentDirId(nextParentAttachmentDirId);
                    attachmentDirectoryInstEntity.setAttachmentDirName(fileName);
                    attachmentDirectoryInstEntity.setBusinessId(ywid);
                    attachmentDirectoryInstEntity.setSortNo(dirNum);
                    attachmentDirectoryInstEntity.setBusinessCode(ywxl);
                    attachmentDirectoryInstEntity.setIsRequired(0);
                    attachmentDirectoryInstEntity.setMaterialSource(materialSource);
                    attachmentDirectoryInstEntity.setIsRequiredOriginal("0");
                    attachmentDirectoryInstEntity.setFilterTags(ywxl);
                    attachmentDirectoryInstEntity.setCreateUserId(userId);
                    attachmentDirectoryInstEntity.setCreateUserName(userName);
                    attachmentDirectoryInstEntity.setCreateTime(currentTimestamp);
                    attachmentDirectoryInstMapper.insert(attachmentDirectoryInstEntity);
                    if(version > 1) {
                        // 新增补正附件记录
                        CorrectionAttachmentEntity correctionAttachmentEntity = new CorrectionAttachmentEntity();
                        correctionAttachmentEntity.setId(StringUtil.getUUID());
                        correctionAttachmentEntity.setBusinessId(ywid);
                        correctionAttachmentEntity.setAttachmentId(attachmentId);
                        correctionAttachmentEntity.setType(1);
                        correctionAttachmentEntity.setVersion(version);
                        correctionAttachmentEntity.setCreateUserId(userId);
                        correctionAttachmentEntity.setCreateUserName(userName);
                        correctionAttachmentEntity.setCreateTime(currentTimestamp);
                        correctionAttachmentMapper.insert(correctionAttachmentEntity);
                    }
                    saveAttachmentDir(params, ywid, ywxl, userId, userName, files[i].getCanonicalPath(), nextParentAttachmentDirId, version);
                }
            }
        }
    }

    /**
     * 上传文件
     * @param filePath
     * @param attachmentName
     * @param attachmentDirId
     * @param sortNo
     * @param attachmentType
     * @param attachmentExtension
     * @param userId
     * @param userName
     * @param attachmentInfo
     * @param businessId
     * @param businessType
     * @param ocr
     * @param isPublic
     * @param version
     * @throws Exception
     */
    public void uploadFile(String filePath, String attachmentName, String attachmentDirId, Integer sortNo, String attachmentType, String attachmentExtension,
                           String userId, String userName, String attachmentInfo, String businessId, String businessType, Integer ocr, Integer isPublic, Integer version) throws Exception {
        // 当前时间
        Timestamp currentTimestamp = new Timestamp(new Date().getTime());
        String attachmentId = null;
        long attachmentSize = 0l;
        Map<String, String> uploadFileParam = new HashMap<String, String>();
        uploadFileParam.put("comeFrom", "OA");
        uploadFileParam.put("userId", userId);
        uploadFileParam.put("doOCR", "no");
        Map<String, String> fileMap = new HashMap<String, String>();
        fileMap.put("filePath", filePath);
        ServerResponse responseResult = proxy.mongoDBUtil.doPost(proxy.uploadFileUrl, uploadFileParam, fileMap);
        int status = responseResult.getStatus();
        if (HttpStatus.SC_OK == status) {
            LinkedHashMap data = (LinkedHashMap) responseResult.getData();
            attachmentId = (String) data.get("fileId");
            attachmentSize = Long.parseLong(data.get("size").toString());
        } else {
            throw new Exception("文件上传异常");
        }
        /** 新增附件记录 */
        if(StringUtils.isBlank(attachmentInfo)) {
            attachmentInfo = attachmentId;
        }
        String attachmentPrimaryId = StringUtil.getUUID();
        AttachmentEntity attachmentEntity = new AttachmentEntity();
        attachmentEntity.setId(attachmentPrimaryId);
        attachmentEntity.setAttachmentId(attachmentId);
        attachmentEntity.setAttachmentName(attachmentName);
        attachmentEntity.setAttachmentDirId(attachmentDirId);
        attachmentEntity.setAttachmentSize(attachmentSize);
        attachmentEntity.setSortNo(sortNo);
        attachmentEntity.setAttachmentType(attachmentType);
        attachmentEntity.setAttachmentExtension(attachmentExtension);
        attachmentEntity.setUploadUserId(userId);
        attachmentEntity.setUploadUserName(userName);
        attachmentEntity.setUploadTime(currentTimestamp);
        attachmentEntity.setAttachmentInfo(attachmentInfo);
        attachmentEntity.setBusinessId(businessId);
        attachmentEntity.setBusinessType(businessType);
        attachmentEntity.setIsDel(0);
        attachmentEntity.setOcr(ocr);
        attachmentEntity.setIsPublic(isPublic);
        proxy.attachmentMapper.insert(attachmentEntity);
        if(version > 1) {
            // 新增补正附件记录
            CorrectionAttachmentEntity correctionAttachmentEntity = new CorrectionAttachmentEntity();
            correctionAttachmentEntity.setId(StringUtil.getUUID());
            correctionAttachmentEntity.setBusinessId(businessId);
            correctionAttachmentEntity.setAttachmentId(attachmentPrimaryId);
            correctionAttachmentEntity.setType(0);
            correctionAttachmentEntity.setVersion(version);
            correctionAttachmentEntity.setCreateUserId(userId);
            correctionAttachmentEntity.setCreateUserName(userName);
            correctionAttachmentEntity.setCreateTime(currentTimestamp);
            proxy.correctionAttachmentMapper.insert(correctionAttachmentEntity);
            // 新增附件版本记录
//            AttachmentVersionEntity attachmentVersionEntity = new AttachmentVersionEntity();
//            attachmentVersionEntity.setId(StringUtil.getUUID());
//            attachmentVersionEntity.setBusinessId(businessId);
//            attachmentVersionEntity.setAttachmentId(attachmentPrimaryId);
//            attachmentVersionEntity.setAttachmentName(attachmentName);
//            attachmentVersionEntity.setVersion(version.toString());
//            attachmentVersionEntity.setCreateUserId(userId);
//            attachmentVersionEntity.setCreateUserName(userName);
//            attachmentVersionEntity.setCreateTime(currentTimestamp);
//            proxy.attachmentVersionMapper.insert(attachmentVersionEntity);
        }
    }
}
